package com.zeji.androidadvance.activity.littleAd;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import com.zeji.androidadvance.R;
import com.zeji.androidadvance.utils.RxUtil;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.disposables.Disposable;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;

public class LittleAdView extends View {
    private final Paint paint;
    private Disposable moveDisposable;
    private int nowPos = 0;
    private final List<String> values = new CopyOnWriteArrayList<>();

    private final Config config = new Config(50, 1000, 2000);
    private State nowState = State.move;

    public LittleAdView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(ContextCompat.getColor(context, R.color.purple_500));
        paint.setTextAlign(Paint.Align.CENTER);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (nowPos >= values.size()) {
            return;
        }
        String nowStr = values.get(nowPos);
        String nextStr = values.get((nowPos + 1) % values.size());
        paint.setTextSize(getHeight());

        float offset = (float) getHeight() * nowState.time / config.switchTime;
        float lineY = (float) getHeight() * 5 / 6 - offset;
        float lineX = (float) getWidth() / 2;
        canvas.drawText(nowStr, lineX, lineY, paint);
        canvas.drawText(nextStr, lineX, lineY + getHeight(), paint);
    }

    public void setValues(List<String> values) {
        this.values.clear();
        this.values.addAll(values);
    }

    public void start() {
        end();
        if (values.isEmpty()) {
            return;
        }
        moveDisposable = Observable.interval(1000 / config.frame, TimeUnit.MILLISECONDS)
                .filter(ignore -> {
                    nowState.time += 1000 / config.frame;
                    if (nowState == State.hold) {
                        if (nowState.time >= config.holdTime) {
                            nowState.time = 0;
                            nowState = State.move;
                        }
                        return false;
                    } else {
                        if (nowState.time >= config.switchTime) {
                            nowState.time = 0;
                            nowPos = (nowPos + 1) % values.size();
                            nowState = State.hold;
                        }
                        return true;
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(time -> invalidate());
    }

    public void end() {
        RxUtil.dispose(moveDisposable);
        nowPos = 0;
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        end();
    }

    private static class Config {
        /**
         * 帧率
         */
        int frame;
        /**
         * 切换时长，毫秒
         */
        int switchTime;
        /**
         * 停留时长，毫秒
         */
        int holdTime;

        public Config(int frame, int switchTime, int holdTime) {
            this.frame = frame;
            this.switchTime = switchTime;
            this.holdTime = holdTime;
        }
    }

    private enum State {
        move(0),
        hold(0);

        private int time;

        State(int time) {
            this.time = time;
        }
    }
}
